package com.eqs.enterprisequestionnaire.service;

import com.eqs.enterprisequestionnaire.model.pojo.Answer;
import com.eqs.enterprisequestionnaire.model.pojo.Question;
import com.eqs.enterprisequestionnaire.model.pojo.Response;
import com.eqs.enterprisequestionnaire.result.R;
import jakarta.annotation.Resource;
import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.stat.correlation.KendallsCorrelation;
import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
import org.apache.commons.math3.stat.correlation.SpearmansCorrelation;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import static com.eqs.enterprisequestionnaire.model.enums.QuestionEnum.*;

@Service
public class CorrelationAnalysisService {
    @Resource
    private QuestionService questionService;
    @Resource
    private AnswerService answerService;
    @Resource
    private OptionService optionService;
    @Resource
    private ResponseService responseService;


    private static final double NOVALUE = Double.NaN;

    //pearson常量
    public static final String PEARSON_ID = "1001";
    //spearman常量
    public static final String SPEARMAN_ID = "1002";
    //Kendall 常量
    public static final String KENDALL_ID = "1003";
    /*
     * 单选题与单选题的相关性分析
     * */
    public Double correlationOqTOq(Integer questionId1,Integer questionId2,String methodId){

        double[] xArray=questionToDouble(questionId1);
        double[] yArray=questionToDouble(questionId2);
        int i=0;
        return correlation(xArray,yArray,methodId);
    }
    /*
     * 单选题与选项(多选题、排序题、程度题)的相关性分析
     * */
    public Double correlationOqTO(Integer questionId, Integer optionId,String methodId){

        double[] xArray=questionToDouble(questionId);
        double[] yArray=optionToDouble(optionId);

        return correlation(xArray,yArray,methodId);
    }
    /*
     * 选项和选项的相关性分析
     * */
    public Double correlationOTO(Integer optionId1, Integer optionId2,String methodId){

        double[] xArray=optionToDouble(optionId1);
        double[] yArray=optionToDouble(optionId2);

        return correlation(xArray,yArray,methodId);
    }

    /*
     * 初始化问题Double[]
     * */
    public double[] questionToDouble(Integer questionId) {

        //获取该问题的所以答案(以答卷Id排序)
        List<Answer> answers=answerService.selectAllAnswerByQuestion(questionId);
        Comparator<Answer> answerComparator = Comparator.comparing(Answer::getResponseId);
        Collections.sort(answers,answerComparator);
        //转Double数组
        double[] Array=new double[answers.size()];
        int i=0;
        for (Answer a:answers) {
            Array[i]=Double.parseDouble(a.getContent());
            i++;
        }
        return Array;
    }
    /*
     * 初始化选项Double[]
     * */
    public double[] optionToDouble(Integer optionId) {

        //该选项对应的题
        Question question =
                questionService.selectByQuestionId(optionService.getById(optionId).getQuestionId());

        //改选项对应的所有答卷(以答卷Id排序)
        List<Response> responses=responseService.selectAllResponse(question.getQuestionnaireId());
        Comparator<Response> responseComparator = Comparator.comparing(Response::getId);
        Collections.sort(responses,responseComparator);
        //转Double数组
        double[] Array=new double[responses.size()];
        int i=0;

        //如果是多选题选项
        if(MULTIPLE_CHOICE.getType().equalsIgnoreCase(question.getType())){
            for (Response r:responses) {
                Array[i]=0;
                //查询这份答卷这道题的答案
                Answer answer=new Answer();
                answer.setResponseId(r.getId());
                answer.setQuestionId(question.getId());
                List<Answer> answers =answerService.selectAll(answer);
                //判断此选项是否当选
                for (Answer a:answers){
                    if(Double.parseDouble(a.getContent())==optionId){
                        Array[i]=1;
                        break;
                    }
                }
                i++;
            }
        }  else if(LEVELQUESTION.getType().equalsIgnoreCase(question.getType())){//程度题选项
            for (Response r:responses) {
                Array[i] = 0;
                //查询这份答卷这道题这个选项的答案
                Answer answer=new Answer();
                answer.setResponseId(r.getId());
                answer.setQuestionId(question.getId());
                answer.setContent(optionId.toString());
                List<Answer> answers =answerService.selectAll(answer);//应只有一个
                if(answers.size()!=1){
                    throw new IllegalArgumentException("Question is not of a level type.");
                }   else {
                    Array[i] =answers.get(0).getLevel();
                }
                i++;
            }
        }   else if(SORTQUESTION.getType().equalsIgnoreCase(question.getType())){//排序题选项
            for (Response r:responses) {
                Array[i] = 0;
                //查询这份答卷这道题这个选项的答案
                Answer answer=new Answer();
                answer.setResponseId(r.getId());
                answer.setQuestionId(question.getId());
                answer.setContent(optionId.toString());
                List<Answer> answers =answerService.selectAll(answer);//应只有一个
                if(answers.size()!=1){
                    throw new IllegalArgumentException("Question is not of a sort type.");
                }   else {
                    Array[i] =(Integer.parseInt(answers.get(0).getText()));
                }
                i++;
            }
        }
        return Array;
    }
    /*
     * 相关性系数计算
     * */
    public double correlation(final double[] xArray, final double[] yArray, String methodId) {

        if(xArray.length!=yArray.length){
            throw new DimensionMismatchException(xArray.length, yArray.length);
        } else if(xArray.length<2){
            return NOVALUE;
        } else {
            if(PEARSON_ID.equals(methodId)) {
                PearsonsCorrelation pearsonsCorrelation = new PearsonsCorrelation();
                return pearsonsCorrelation.correlation(xArray,yArray);
            } else if(SPEARMAN_ID.equals(methodId)) {
                SpearmansCorrelation spearmansCorrelation =new SpearmansCorrelation();
                return spearmansCorrelation.correlation(xArray,yArray);
            }   else if(KENDALL_ID.equals(methodId)) {
                KendallsCorrelation kendallsCorrelation=new KendallsCorrelation();
                return kendallsCorrelation.correlation(xArray,yArray);
            }
        }
        return NOVALUE;
    }
}
